---
description: 如何維護更新日誌
title: 如何維護更新日誌
language: zh-TW
version: 1.0.0
---

- changelog = "https://github.com/olivierlacan/keep-a-changelog/blob/master/CHANGELOG.md"
- gh = "https://github.com/olivierlacan/keep-a-changelog"
- issues = "https://github.com/olivierlacan/keep-a-changelog/issues"
- semver = "https://semver.org/lang/zh-TW/"
- shields = "https://shields.io/"
- thechangelog = "https://changelog.com/podcast/127"
- vandamme = "https://github.com/tech-angels/vandamme/"
- iso = "http://www.iso.org/iso/home/standards/iso8601.htm"
- ghr = "https://help.github.com/articles/creating-releases/"
- gnu_changelog_styleguide = "https://www.gnu.org/prep/standards/html_node/Change-Logs.html"
- gnu_the_news = "https://www.gnu.org/prep/standards/html_node/NEWS-File.html"

.header
  .title
    %h1 如何維護更新日誌
    %h2 更新日誌絕對不應該只是 git log 的堆砌物

  = link_to changelog do
    Version
    %strong= current_page.metadata[:page][:version]

  %pre.changelog= File.read("CHANGELOG.md")

.answers
  %h3#what
    %a.anchor{ href: "#what", aria_hidden: "true" }
    更新日誌是什麼？

  %p
    更新日誌（Changelog）是個記錄專案演進版本間的差異，以時間倒敘、由人工攥寫的列表。

  %h3#why
    %a.anchor{ href: "#why", aria_hidden: "true" }
    為什麼需要提供更新日誌？

  %p
    為了讓使用者和開發人員更簡單明確地了解各個版本之間有著哪些改動。

  %h3#who
    %a.anchor{ href: "#who", aria_hidden: "true" }
    哪些人需要更新日誌？

  %p
    大家都需要更新日誌。無論是使用者還是開發者，軟體最終的用戶都會在意軟體包含了什麼。當軟體更新了，大家會希望知道改了什麼、為什麼要改。

.good-practices
  %h3#how
    %a.anchor{ href: "#how", aria_hidden: "true" }
    如何寫出高品質的日誌？

  %h4#principles
    %a.anchor{ href: "#principles", aria_hidden: "true" }
    指導原則

  %ul
    %li
      日誌是寫給「人」看的，不是機器。
    %li
      每個版本都應該有獨立的進入點。
    %li
      相同類型的改動應分組放置。
    %li
      版本與章節應「可連結化」。
    %li
      新版本總是寫在前面。
    %li
      每個版本都該註記發佈日期。
    %li
      版本命名應遵守#{link_to "語意化版本", semver}格式。

  %a.anchor{ href: "#types", aria_hidden: "true" }
  %h4#types 改動類型

  %ul
    %li
      %code Added
      當增加了新功能。
    %li
      %code Changed
      當更動了既有的功能。
    %li
      %code Deprecated
      當功能將在近期被移除。
    %li
      %code Removed
      當移除了現有的功能。
    %li
      %code Fixed
      當修復了某些錯誤。
    %li
      %code Security
      當增進了安全性漏洞。

.effort

  %h3#effort
    %a.anchor{ href: "#effort", aria_hidden: "true" }
    如何提升維護更新日誌的效率？

  %p
    在日誌上方使用 <code>Unreleased</code> 區塊記錄即將發佈的更新內容。

  %p 這麼做能夠：

  %ul
    %li
      讓大家知道在未來的版本中可能會有哪些改動。
    %li
      發佈新版本時，直接將 <code>Unreleased</code> 移到新版本的區塊就完成了 ヾ(*´ω｀*)ノ

.bad-practices
  %h3#bad-practices
    %a.anchor{ href: "#bad-practices", aria_hidden: "true" }
    難道日誌能寫得很糟嗎？

  %p 當然。下面有些糟糕的範例：

  %h4#log-diffs
    %a.anchor{ href: "#log-diffs", aria_hidden: "true" }
    🚫 直接使用 git log

  %p
    使用 git log 作為更新日誌絕對不是個好主意：git log 充滿了各種無意義的訊息，像 merge commits
    、亂七八糟的提交訊息、文件更新等。

  %p
    Commits 的目的應該是記錄原始碼的演化過程。有些項目會清理 commits，有些卻不會。

  %p
    更新日誌的目的則是記錄那些值得一提的改動，經常涵蓋多個 commits，最終目的仍是讓使用者一目了然。

  %h4#ignoring-deprecations
    %a.anchor{ href: "#ignoring-deprecations", aria_hidden: "true" }
    🚫 忽略 Deprecations

  %p
    當使用者升級版本時，他應該要能預先知道哪些環節可能會出問題。理想的情形下，應該讓使用者有空間能預先升級即將被棄用的功能；待替換掉棄用功能之後，再升級至棄用功能被真正移除的版本。

  %p
    即使不這麼做，也要在更新日誌中列出棄用的、移除的、或是任何可能導致程式碼失效的重大改動。

  %h4#confusing-dates
    %a.anchor{ href: "#confusing-dates", aria_hidden: "true" }
    🚫 易混淆的日期格式

  %p
    在世界的每個角落，不同區域有著不同的時間格式，找到讓大家都滿意的日期格式不是件簡單的事。使用像
    <code>2017-07-17</code> 的格式能清楚傳達日期、不易與其他日期格式混淆，同時也遵守
    #{link_to "ISO 標準", iso}，因此推薦使用像這樣的日期格式。

  %aside
    其實還有許多應該避免的。大家可以透過
    = link_to "Issue", issues
    或是 Pull Request 協助蒐集 ฅ' ω 'ฅ

.frequently-asked-questions
  %h3#frequently-asked-questions
    %a.anchor{ href: "#frequently-asked-questions", aria_hidden: "true" }
    常見問題

  %h4#standard
    %a.anchor{ href: "#standard", aria_hidden: "true" }
    有沒有標準格式可以參考呢？

  %p
    並沒有。雖然有 #{link_to "GNU 更新日誌指南", gnu_changelog_styleguide} 以及只有兩段長的
    #{link_to "GNU - The NEWS File 指南", gnu_the_news}（括弧笑），但這些並不足以稱為「標準」。

  %p
    這項專案的宗旨在於提供一個
    #{link_to "更好的更新日誌範例", changelog}，源於觀察開源社群中優秀的實際案例，把它們蒐集在一起。

  %p
    歡迎各位#{link_to "提供", issues}有建設性的建議和批評。

  %h4#filename
    %a.anchor{ href: "#filename", aria_hidden: "true" }
    更新日誌的檔案名稱應該是？

  %p
    通常使用 <code>CHANGELOG.md</code>。也有用
    <code>HISTORY</code>、<code>NEWS</code>、或是 <code>RELEASES</code> 的例子。

  %p
    或許你認為取什麼名字並不是件多麼重要的事，但為什麼要讓只是想看日誌的使用者不容易找到它呢？

  %h4#github-releases
    %a.anchor{ href: "#github-releases", aria_hidden: "true" }
    那麼 GitHub Releases 呢？

  %p
    這是個好問題。#{link_to "GitHub Releases", ghr}
    能手動在簡單的 git tag（如
    <code>v1.0.0</code>） 上附加豐富的版本資訊，也能把附帶的 tag
    messages 轉換成漂亮的日誌格式。

  %p
    GitHub Releases 產生的日誌只能在 GitHub 上瀏覽，雖然 GitHub Releases
    能做出接近本專案範例的日誌格式，但這會增加些許與 GitHub 的相依性。

  %p
    現行的 GitHub Releases
    畢竟不像典型的大寫文件（<code>README</code>、<code>CONTRIBUTING</code>
    之類的），按理說會增加使用者找到的難度。另外還有個小問題，目前 GitHub
    Releases 頁面上並沒有提供兩版版本之間 commit logs 的連結。

  %h4#automatic
    %a.anchor{ href: "#automatic", aria_hidden: "true" }
    更新日誌能被自動生成嗎？

  %p
    非常困難，各式各樣的提交訊息和檔案名稱難以完全掌握。

  %p
    另外，有些開源專案使用由 Gemnasium
    團隊開發的 #{link_to "Vandamme", vandamme}
    轉換更新日誌，或許可以當作參考。

  %h4#yanked
    %a.anchor{ href: "#yanked", aria_hidden: "true" }
    那麼被撤下的版本呢？

  %p
    因為重大漏洞或安全性問題而被撤下（unpublished）的版本通常不會出現在日誌裡，但建議仍然記錄下來。你可以這樣記錄它們：

  %p <code>## [0.0.5] - 2014-12-13 [YANKED]</code>

  %p
    其中 <code>[YANKED]</code> 標記應該和原因顯眼地標示在一起，讓使用者注意到它是最重要的事。此外，用中括弧能讓轉換用的程式更容易辨認它們。

  %h4#rewrite
    %a.anchor{ href: "#rewrite", aria_hidden: "true" }
    可以更改過去版本的日誌內容嗎？

  %p
    當然可以，總是會有好的原因來改善以往寫下的日誌。我也時常發 pull request
    給更新日誌不齊全的開源專案。

  %p
    偶爾會發現自己遺漏了某項重大更新的紀錄，很明顯你應該補齊它們。

  %h4#contribute
    %a.anchor{ href: "#contribute", aria_hidden: "true" }
    我能做些什麼嗎？

  %p
    這份文件並不是《真理》，而是我經過深思熟慮、遵循蒐集到的資訊和範例之後提出的建議。

  %p
    源於我期望社群能達到共識，我相信討論的過程與結果一樣重要。

  %p
    所以，<strong>#{link_to "加入我們", gh}</strong>吧 ٩(｡・ω・｡)﻿و

.press
  %h3 訪談
  %p
    我在 #{link_to "The Changelog podcast", thechangelog} 上講述了為什麼維護者與協作者應該在意更新日誌，以及建立這項專案背後的契機。
